package it.polimi.dei.SeCo.GeoNames;

import it.polimi.dei.SeCo.YAGO.GeoEntity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.geonames.InsufficientStyleException;
import org.geonames.Style;
import org.geonames.Toponym;
import org.geonames.ToponymSearchCriteria;
import org.geonames.ToponymSearchResult;
import org.geonames.WebService;

/**
 * @author Simone Benefico
 */
public class GeoNamesTool {
	
	public static final Map<String, String> featureCodeNames = new HashMap<String, String>();
	
	/**
	 * Sets the GeoNames username and fill the map of featureClasses from GeoNames.
	 * @param username username used to access GeoNames APIs
	 */
	public GeoNamesTool (String username) {
		WebService.setUserName(username);
		featureCodeNames.put("ADM1", "first-order administrative division");
		featureCodeNames.put("ADM2", "second-order administrative division");
		featureCodeNames.put("ADM3", "third-order administrative division");
		featureCodeNames.put("ADM4", "fourth-order administrative division");
		featureCodeNames.put("ADMD", "administrative division");
		featureCodeNames.put("LTER", "leased area");
		featureCodeNames.put("PCL", "political entity");
		featureCodeNames.put("PCLD", "dependent political entity");
		featureCodeNames.put("PCLF", "freely associated state");
		featureCodeNames.put("PCLI", "independent political entity");
		featureCodeNames.put("PCLIX", "section of independent political entity");
		featureCodeNames.put("PCLS", "semi-independent political entity");
		featureCodeNames.put("PRSH", "parish");
		featureCodeNames.put("TERR", "territory");
		featureCodeNames.put("ZN", "zone");
		featureCodeNames.put("ZNB", "buffer zone");
		featureCodeNames.put("AIRS", "seaplane landing area");
		featureCodeNames.put("ANCH", "anchorage");
		featureCodeNames.put("BAY", "bay");
		featureCodeNames.put("BAYS", "bays");
		featureCodeNames.put("BGHT", "bight");
		featureCodeNames.put("BNK", "bank");
		featureCodeNames.put("BNKR", "stream bank");
		featureCodeNames.put("BNKX", "section of bank");
		featureCodeNames.put("BOG", "bog");
		featureCodeNames.put("CAPG", "icecap");
		featureCodeNames.put("CHN", "channel");
		featureCodeNames.put("CHNL", "lake channel");
		featureCodeNames.put("CHNM", "marine channel");
		featureCodeNames.put("CHNN", "navigation channel");
		featureCodeNames.put("CNFL", "confluence");
		featureCodeNames.put("CNL", "canal");
		featureCodeNames.put("CNLA", "aqueduct");
		featureCodeNames.put("CNLB", "canal bend");
		featureCodeNames.put("CNLD", "drainage canal");
		featureCodeNames.put("CNLI", "irrigation canal");
		featureCodeNames.put("CNLN", "navigation canal");
		featureCodeNames.put("CNLQ", "abandoned canal");
		featureCodeNames.put("CNLSB", "underground irrigation canal");
		featureCodeNames.put("CNLX", "section of canal");
		featureCodeNames.put("COVE", "cove");
		featureCodeNames.put("CRKT", "tidal creek");
		featureCodeNames.put("CRNT", "current");
		featureCodeNames.put("CUTF", "cutoff");
		featureCodeNames.put("DCK", "dock");
		featureCodeNames.put("DCKB", "docking basin");
		featureCodeNames.put("DOMG", "icecap dome");
		featureCodeNames.put("DPRG", "icecap depression");
		featureCodeNames.put("DTCH", "ditch");
		featureCodeNames.put("DTCHD", "drainage ditch");
		featureCodeNames.put("DTCHI", "irrigation ditch");
		featureCodeNames.put("DTCHM", "ditch mouth");
		featureCodeNames.put("ESTY", "estuary");
		featureCodeNames.put("FISH", "fishing area");
		featureCodeNames.put("FJD", "fjord");
		featureCodeNames.put("FJDS", "fjords");
		featureCodeNames.put("FLLS", "waterfall");
		featureCodeNames.put("FLLSX", "section of waterfall");
		featureCodeNames.put("FLTM", "mud flat");
		featureCodeNames.put("FLTT", "tidal flat");
		featureCodeNames.put("GLCR", "glacier");
		featureCodeNames.put("GULF", "gulf");
		featureCodeNames.put("GYSR", "geyser");
		featureCodeNames.put("HBR", "harbor");
		featureCodeNames.put("HBRX", "section of harbor");
		featureCodeNames.put("INLT", "inlet");
		featureCodeNames.put("INLTQ", "former inlet");
		featureCodeNames.put("LBED", "lake bed");
		featureCodeNames.put("LGN", "lagoon");
		featureCodeNames.put("LGNS", "lagoons");
		featureCodeNames.put("LGNX", "section of lagoon");
		featureCodeNames.put("LK", "lake");
		featureCodeNames.put("LKC", "crater lake");
		featureCodeNames.put("LKI", "intermittent lake");
		featureCodeNames.put("LKN", "salt lake");
		featureCodeNames.put("LKNI", "intermittent salt lake");
		featureCodeNames.put("LKO", "oxbow lake");
		featureCodeNames.put("LKOI", "intermittent oxbow lake");
		featureCodeNames.put("LKS", "lakes");
		featureCodeNames.put("LKSB", "underground lake");
		featureCodeNames.put("LKSC", "crater lakes");
		featureCodeNames.put("LKSI", "intermittent lakes");
		featureCodeNames.put("LKSN", "salt lakes");
		featureCodeNames.put("LKSNI", "intermittent salt lakes");
		featureCodeNames.put("LKX", "section of lake");
		featureCodeNames.put("MFGN", "salt evaporation ponds");
		featureCodeNames.put("MGV", "mangrove swamp");
		featureCodeNames.put("MOOR", "moor");
		featureCodeNames.put("MRSH", "marsh");
		featureCodeNames.put("MRSHN", "salt marsh");
		featureCodeNames.put("NRWS", "narrows");
		featureCodeNames.put("OCN", "ocean");
		featureCodeNames.put("OVF", "overfalls");
		featureCodeNames.put("PND", "pond");
		featureCodeNames.put("PNDI", "intermittent pond");
		featureCodeNames.put("PNDN", "salt pond");
		featureCodeNames.put("PNDNI", "intermittent salt pond");
		featureCodeNames.put("PNDS", "ponds");
		featureCodeNames.put("PNDSF", "fishponds");
		featureCodeNames.put("PNDSI", "intermittent ponds");
		featureCodeNames.put("PNDSN", "salt ponds");
		featureCodeNames.put("POOL", "pool");
		featureCodeNames.put("POOLI", "intermittent pool");
		featureCodeNames.put("RCH", "reach");
		featureCodeNames.put("RDGG", "icecap ridge");
		featureCodeNames.put("RDST", "roadstead");
		featureCodeNames.put("RF", "reef");
		featureCodeNames.put("RFC", "coral reef");
		featureCodeNames.put("RFX", "section of reef");
		featureCodeNames.put("RPDS", "rapids");
		featureCodeNames.put("RSV", "reservoir");
		featureCodeNames.put("RSVI", "intermittent reservoir");
		featureCodeNames.put("RSVT", "water tank");
		featureCodeNames.put("RVN", "ravine");
		featureCodeNames.put("SBKH", "sabkha");
		featureCodeNames.put("SD", "sound");
		featureCodeNames.put("SEA", "sea");
		featureCodeNames.put("SHOL", "shoal");
		featureCodeNames.put("SILL", "sill");
		featureCodeNames.put("SPNG", "spring");
		featureCodeNames.put("SPNS", "sulphur spring");
		featureCodeNames.put("SPNT", "hot spring");
		featureCodeNames.put("STM", "stream");
		featureCodeNames.put("STMA", "anabranch");
		featureCodeNames.put("STMB", "stream bend");
		featureCodeNames.put("STMC", "canalized stream");
		featureCodeNames.put("STMD", "distributary");
		featureCodeNames.put("STMH", "headwaters");
		featureCodeNames.put("STMI", "intermittent stream");
		featureCodeNames.put("STMIX", "section of intermittent stream");
		featureCodeNames.put("STMM", "stream mouth");
		featureCodeNames.put("STMQ", "abandoned watercourse");
		featureCodeNames.put("STMS", "streams");
		featureCodeNames.put("STMSB", "lost river");
		featureCodeNames.put("STMX", "section of stream");
		featureCodeNames.put("STRT", "strait");
		featureCodeNames.put("SWMP", "swamp");
		featureCodeNames.put("SYSI", "irrigation system");
		featureCodeNames.put("TNLC", "canal tunnel");
		featureCodeNames.put("WAD", "wadi");
		featureCodeNames.put("WADB", "wadi bend");
		featureCodeNames.put("WADJ", "wadi junction");
		featureCodeNames.put("WADM", "wadi mouth");
		featureCodeNames.put("WADS", "wadies");
		featureCodeNames.put("WADX", "section of wadi");
		featureCodeNames.put("WHRL", "whirlpool");
		featureCodeNames.put("WLL", "well");
		featureCodeNames.put("WLLQ", "abandoned well");
		featureCodeNames.put("WLLS", "wells");
		featureCodeNames.put("WTLD", "wetland");
		featureCodeNames.put("WTLDI", "intermittent wetland");
		featureCodeNames.put("WTRC", "watercourse");
		featureCodeNames.put("WTRH", "waterhole");
		featureCodeNames.put("AGRC", "agricultural colony");
		featureCodeNames.put("AMUS", "amusement park");
		featureCodeNames.put("AREA", "area");
		featureCodeNames.put("BSND", "drainage basin");
		featureCodeNames.put("BSNP", "petroleum basin");
		featureCodeNames.put("BTL", "battlefield");
		featureCodeNames.put("CLG", "clearing");
		featureCodeNames.put("CMN", "common");
		featureCodeNames.put("CNS", "concession area");
		featureCodeNames.put("COLF", "coalfield");
		featureCodeNames.put("CONT", "continent");
		featureCodeNames.put("CST", "coast");
		featureCodeNames.put("CTRB", "business center");
		featureCodeNames.put("DEVH", "housing development");
		featureCodeNames.put("FLD", "field");
		featureCodeNames.put("FLDI", "irrigated field");
		featureCodeNames.put("GASF", "gasfield");
		featureCodeNames.put("GRAZ", "grazing area");
		featureCodeNames.put("GVL", "gravel area");
		featureCodeNames.put("INDS", "industrial area");
		featureCodeNames.put("LAND", "arctic land");
		featureCodeNames.put("LCTY", "locality");
		featureCodeNames.put("MILB", "military base");
		featureCodeNames.put("MNA", "mining area");
		featureCodeNames.put("MVA", "maneuver area");
		featureCodeNames.put("NVB", "naval base");
		featureCodeNames.put("OAS", "oasis");
		featureCodeNames.put("OILF", "oilfield");
		featureCodeNames.put("PEAT", "peat cutting area");
		featureCodeNames.put("PRK", "park");
		featureCodeNames.put("PRT", "port");
		featureCodeNames.put("QCKS", "quicksand");
		featureCodeNames.put("RES", "reserve");
		featureCodeNames.put("RESA", "agricultural reserve");
		featureCodeNames.put("RESF", "forest reserve");
		featureCodeNames.put("RESH", "hunting reserve");
		featureCodeNames.put("RESN", "nature reserve");
		featureCodeNames.put("RESP", "palm tree reserve");
		featureCodeNames.put("RESV", "reservation");
		featureCodeNames.put("RESW", "wildlife reserve");
		featureCodeNames.put("RGN", "region");
		featureCodeNames.put("RGNE", "economic region");
		featureCodeNames.put("RGNL", "lake region");
		featureCodeNames.put("RNGA", "artillery range");
		featureCodeNames.put("SALT", "salt area");
		featureCodeNames.put("SNOW", "snowfield");
		featureCodeNames.put("TRB", "tribal area");
		featureCodeNames.put("PPL", "populated place");
		featureCodeNames.put("PPLA", "seat of a first-order administrative division");
		featureCodeNames.put("PPLA2", "seat of a second-order administrative division");
		featureCodeNames.put("PPLA3", "seat of a third-order administrative division");
		featureCodeNames.put("PPLA4", "seat of a fourth-order administrative division");
		featureCodeNames.put("PPLC", "capital of a political entity");
		featureCodeNames.put("PPLF", "farm village");
		featureCodeNames.put("PPLG", "seat of government of a political entity");
		featureCodeNames.put("PPLL", "populated locality");
		featureCodeNames.put("PPLQ", "abandoned populated place");
		featureCodeNames.put("PPLR", "religious populated place");
		featureCodeNames.put("PPLS", "populated places");
		featureCodeNames.put("PPLW", "destroyed populated place");
		featureCodeNames.put("PPLX", "section of populated place");
		featureCodeNames.put("STLMT", "israeli settlement");
		featureCodeNames.put("CSWY", "causeway");
		featureCodeNames.put("OILP", "oil pipeline");
		featureCodeNames.put("PRMN", "promenade");
		featureCodeNames.put("PTGE", "portage");
		featureCodeNames.put("RD", "road");
		featureCodeNames.put("RDA", "ancient road");
		featureCodeNames.put("RDB", "road bend");
		featureCodeNames.put("RDCUT", "road cut");
		featureCodeNames.put("RDJCT", "road junction");
		featureCodeNames.put("RJCT", "railroad junction");
		featureCodeNames.put("RR", "railroad");
		featureCodeNames.put("RRQ", "abandoned railroad");
		featureCodeNames.put("RTE", "caravan route");
		featureCodeNames.put("RYD", "railroad yard");
		featureCodeNames.put("ST", "street");
		featureCodeNames.put("STKR", "stock route");
		featureCodeNames.put("TNL", "tunnel");
		featureCodeNames.put("TNLN", "natural tunnel");
		featureCodeNames.put("TNLRD", "road tunnel");
		featureCodeNames.put("TNLRR", "railroad tunnel");
		featureCodeNames.put("TNLS", "tunnels");
		featureCodeNames.put("TRL", "trail");
		featureCodeNames.put("ADMF", "administrative facility");
		featureCodeNames.put("AGRF", "agricultural facility");
		featureCodeNames.put("AIRB", "airbase");
		featureCodeNames.put("AIRF", "airfield");
		featureCodeNames.put("AIRH", "heliport");
		featureCodeNames.put("AIRP", "airport");
		featureCodeNames.put("AIRQ", "abandoned airfield");
		featureCodeNames.put("AMTH", "amphitheater");
		featureCodeNames.put("ANS", "ancient site");
		featureCodeNames.put("AQC", "aquaculture facility");
		featureCodeNames.put("ARCH", "arch");
		featureCodeNames.put("ASTR", "astronomical station");
		featureCodeNames.put("ASYL", "asylum");
		featureCodeNames.put("ATHF", "athletic field");
		featureCodeNames.put("ATM", "automatic teller machine");
		featureCodeNames.put("BANK", "bank");
		featureCodeNames.put("BCN", "beacon");
		featureCodeNames.put("BDG", "bridge");
		featureCodeNames.put("BDGQ", "ruined bridge");
		featureCodeNames.put("BLDG", "building");
		featureCodeNames.put("BLDO", "office building");
		featureCodeNames.put("BP", "boundary marker");
		featureCodeNames.put("BRKS", "barracks");
		featureCodeNames.put("BRKW", "breakwater");
		featureCodeNames.put("BSTN", "baling station");
		featureCodeNames.put("BTYD", "boatyard");
		featureCodeNames.put("BUR", "burial cave");
		featureCodeNames.put("BUSTN", "bus station");
		featureCodeNames.put("BUSTP", "bus stop");
		featureCodeNames.put("CARN", "cairn");
		featureCodeNames.put("CAVE", "cave");
		featureCodeNames.put("CH", "church");
		featureCodeNames.put("CMP", "camp");
		featureCodeNames.put("CMPL", "logging camp");
		featureCodeNames.put("CMPLA", "labor camp");
		featureCodeNames.put("CMPMN", "mining camp");
		featureCodeNames.put("CMPO", "oil camp");
		featureCodeNames.put("CMPQ", "abandoned camp");
		featureCodeNames.put("CMPRF", "refugee camp");
		featureCodeNames.put("CMTY", "cemetery");
		featureCodeNames.put("COMC", "communication center");
		featureCodeNames.put("CRRL", "corral");
		featureCodeNames.put("CSNO", "casino");
		featureCodeNames.put("CSTL", "castle");
		featureCodeNames.put("CSTM", "customs house");
		featureCodeNames.put("CTHSE", "courthouse");
		featureCodeNames.put("CTRA", "atomic center");
		featureCodeNames.put("CTRCM", "community center");
		featureCodeNames.put("CTRF", "facility center");
		featureCodeNames.put("CTRM", "medical center");
		featureCodeNames.put("CTRR", "religious center");
		featureCodeNames.put("CTRS", "space center");
		featureCodeNames.put("CVNT", "convent");
		featureCodeNames.put("DAM", "dam");
		featureCodeNames.put("DAMQ", "ruined dam");
		featureCodeNames.put("DAMSB", "sub-surface dam");
		featureCodeNames.put("DARY", "dairy");
		featureCodeNames.put("DCKD", "dry dock");
		featureCodeNames.put("DCKY", "dockyard");
		featureCodeNames.put("DIKE", "dike");
		featureCodeNames.put("DIP", "diplomatic facility");
		featureCodeNames.put("DPOF", "fuel depot");
		featureCodeNames.put("EST", "estate");
		featureCodeNames.put("ESTO", "oil palm plantation");
		featureCodeNames.put("ESTR", "rubber plantation");
		featureCodeNames.put("ESTSG", "sugar plantation");
		featureCodeNames.put("ESTT", "tea plantation");
		featureCodeNames.put("ESTX", "section of estate");
		featureCodeNames.put("FCL", "facility");
		featureCodeNames.put("FNDY", "foundry");
		featureCodeNames.put("FRM", "farm");
		featureCodeNames.put("FRMQ", "abandoned farm");
		featureCodeNames.put("FRMS", "farms");
		featureCodeNames.put("FRMT", "farmstead");
		featureCodeNames.put("FT", "fort");
		featureCodeNames.put("FY", "ferry");
		featureCodeNames.put("GATE", "gate");
		featureCodeNames.put("GDN", "garden");
		featureCodeNames.put("GHAT", "ghat");
		featureCodeNames.put("GHSE", "guest house");
		featureCodeNames.put("GOSP", "gas-oil separator plant");
		featureCodeNames.put("GOVL", "local government office");
		featureCodeNames.put("GRVE", "grave");
		featureCodeNames.put("HERM", "hermitage");
		featureCodeNames.put("HLT", "halting place");
		featureCodeNames.put("HSE", "house");
		featureCodeNames.put("HSEC", "country house");
		featureCodeNames.put("HSP", "hospital");
		featureCodeNames.put("HSPC", "clinic");
		featureCodeNames.put("HSPD", "dispensary");
		featureCodeNames.put("HSPL", "leprosarium");
		featureCodeNames.put("HSTS", "historical site");
		featureCodeNames.put("HTL", "hotel");
		featureCodeNames.put("HUT", "hut");
		featureCodeNames.put("HUTS", "huts");
		featureCodeNames.put("INSM", "military installation");
		featureCodeNames.put("ITTR", "research institute");
		featureCodeNames.put("JTY", "jetty");
		featureCodeNames.put("LDNG", "landing");
		featureCodeNames.put("LEPC", "leper colony");
		featureCodeNames.put("LIBR", "library");
		featureCodeNames.put("LNDF", "landfill");
		featureCodeNames.put("LOCK", "lock");
		featureCodeNames.put("LTHSE", "lighthouse");
		featureCodeNames.put("MALL", "mall");
		featureCodeNames.put("MAR", "marina");
		featureCodeNames.put("MFG", "factory");
		featureCodeNames.put("MFGB", "brewery");
		featureCodeNames.put("MFGC", "cannery");
		featureCodeNames.put("MFGCU", "copper works");
		featureCodeNames.put("MFGLM", "limekiln");
		featureCodeNames.put("MFGM", "munitions plant");
		featureCodeNames.put("MFGPH", "phosphate works");
		featureCodeNames.put("MFGQ", "abandoned factory");
		featureCodeNames.put("MFGSG", "sugar refinery");
		featureCodeNames.put("MKT", "market");
		featureCodeNames.put("ML", "mill");
		featureCodeNames.put("MLM", "ore treatment plant");
		featureCodeNames.put("MLO", "olive oil mill");
		featureCodeNames.put("MLSG", "sugar mill");
		featureCodeNames.put("MLSGQ", "former sugar mill");
		featureCodeNames.put("MLSW", "sawmill");
		featureCodeNames.put("MLWND", "windmill");
		featureCodeNames.put("MLWTR", "water mill");
		featureCodeNames.put("MN", "mine");
		featureCodeNames.put("MNAU", "gold mine");
		featureCodeNames.put("MNC", "coal mine");
		featureCodeNames.put("MNCR", "chrome mine");
		featureCodeNames.put("MNCU", "copper mine");
		featureCodeNames.put("MNFE", "iron mine");
		featureCodeNames.put("MNMT", "monument");
		featureCodeNames.put("MNN", "salt mine");
		featureCodeNames.put("MNQ", "abandoned mine");
		featureCodeNames.put("MNQR", "quarry");
		featureCodeNames.put("MOLE", "mole");
		featureCodeNames.put("MSQE", "mosque");
		featureCodeNames.put("MSSN", "mission");
		featureCodeNames.put("MSSNQ", "abandoned mission");
		featureCodeNames.put("MSTY", "monastery");
		featureCodeNames.put("MTRO", "metro station");
		featureCodeNames.put("MUS", "museum");
		featureCodeNames.put("NOV", "novitiate");
		featureCodeNames.put("NSY", "nursery");
		featureCodeNames.put("OBPT", "observation point");
		featureCodeNames.put("OBS", "observatory");
		featureCodeNames.put("OBSR", "radio observatory");
		featureCodeNames.put("OILJ", "oil pipeline junction");
		featureCodeNames.put("OILQ", "abandoned oil well");
		featureCodeNames.put("OILR", "oil refinery");
		featureCodeNames.put("OILT", "tank farm");
		featureCodeNames.put("OILW", "oil well");
		featureCodeNames.put("OPRA", "opera house");
		featureCodeNames.put("PAL", "palace");
		featureCodeNames.put("PGDA", "pagoda");
		featureCodeNames.put("PIER", "pier");
		featureCodeNames.put("PKLT", "parking lot");
		featureCodeNames.put("PMPO", "oil pumping station");
		featureCodeNames.put("PMPW", "water pumping station");
		featureCodeNames.put("PO", "post office");
		featureCodeNames.put("PP", "police post");
		featureCodeNames.put("PPQ", "abandoned police post");
		featureCodeNames.put("PRKGT", "park gate");
		featureCodeNames.put("PRKHQ", "park headquarters");
		featureCodeNames.put("PRN", "prison");
		featureCodeNames.put("PRNJ", "reformatory");
		featureCodeNames.put("PRNQ", "abandoned prison");
		featureCodeNames.put("PS", "power station");
		featureCodeNames.put("PSH", "hydroelectric power station");
		featureCodeNames.put("PSTB", "border post");
		featureCodeNames.put("PSTC", "customs post");
		featureCodeNames.put("PSTP", "patrol post");
		featureCodeNames.put("PYR", "pyramid");
		featureCodeNames.put("PYRS", "pyramids");
		featureCodeNames.put("QUAY", "quay");
		featureCodeNames.put("RDCR", "traffic circle");
		featureCodeNames.put("RECG", "golf course");
		featureCodeNames.put("RECR", "racetrack");
		featureCodeNames.put("REST", "restaurant");
		featureCodeNames.put("RET", "store");
		featureCodeNames.put("RHSE", "resthouse");
		featureCodeNames.put("RKRY", "rookery");
		featureCodeNames.put("RLG", "religious site");
		featureCodeNames.put("RLGR", "retreat");
		featureCodeNames.put("RNCH", "ranch");
		featureCodeNames.put("RSD", "railroad siding");
		featureCodeNames.put("RSGNL", "railroad signal");
		featureCodeNames.put("RSRT", "resort");
		featureCodeNames.put("RSTN", "railroad station");
		featureCodeNames.put("RSTNQ", "abandoned railroad station");
		featureCodeNames.put("RSTP", "railroad stop");
		featureCodeNames.put("RSTPQ", "abandoned railroad stop");
		featureCodeNames.put("RUIN", "ruin");
		featureCodeNames.put("SCH", "school");
		featureCodeNames.put("SCHA", "agricultural school");
		featureCodeNames.put("SCHC", "college");
		featureCodeNames.put("SCHL", "language school");
		featureCodeNames.put("SCHM", "military school");
		featureCodeNames.put("SCHN", "maritime school");
		featureCodeNames.put("SCHT", "technical school");
		featureCodeNames.put("SECP", "State Exam Prep Centre");
		featureCodeNames.put("SHPF", "sheepfold");
		featureCodeNames.put("SHRN", "shrine");
		featureCodeNames.put("SHSE", "storehouse");
		featureCodeNames.put("SLCE", "sluice");
		featureCodeNames.put("SNTR", "sanatorium");
		featureCodeNames.put("SPA", "spa");
		featureCodeNames.put("SPLY", "spillway");
		featureCodeNames.put("SQR", "square");
		featureCodeNames.put("STBL", "stable");
		featureCodeNames.put("STDM", "stadium");
		featureCodeNames.put("STNB", "scientific research base");
		featureCodeNames.put("STNC", "coast guard station");
		featureCodeNames.put("STNE", "experiment station");
		featureCodeNames.put("STNF", "forest station");
		featureCodeNames.put("STNI", "inspection station");
		featureCodeNames.put("STNM", "meteorological station");
		featureCodeNames.put("STNR", "radio station");
		featureCodeNames.put("STNS", "satellite station");
		featureCodeNames.put("STNW", "whaling station");
		featureCodeNames.put("STPS", "steps");
		featureCodeNames.put("SWT", "sewage treatment plant");
		featureCodeNames.put("THTR", "theater");
		featureCodeNames.put("TMB", "tomb");
		featureCodeNames.put("TMPL", "temple");
		featureCodeNames.put("TNKD", "cattle dipping tank");
		featureCodeNames.put("TOWR", "tower");
		featureCodeNames.put("TRANT", "transit terminal");
		featureCodeNames.put("TRIG", "triangulation station");
		featureCodeNames.put("TRMO", "oil pipeline terminal");
		featureCodeNames.put("TWO", "temp work office");
		featureCodeNames.put("UNIP", "university prep school");
		featureCodeNames.put("UNIV", "university");
		featureCodeNames.put("USGE", "united states government establishment");
		featureCodeNames.put("VETF", "veterinary facility");
		featureCodeNames.put("WALL", "wall");
		featureCodeNames.put("WALLA", "ancient wall");
		featureCodeNames.put("WEIR", "weir");
		featureCodeNames.put("WHRF", "wharf");
		featureCodeNames.put("WRCK", "wreck");
		featureCodeNames.put("WTRW", "waterworks");
		featureCodeNames.put("ZNF", "free trade zone");
		featureCodeNames.put("ZOO", "zoo");
		featureCodeNames.put("ASPH", "asphalt lake");
		featureCodeNames.put("ATOL", "atoll");
		featureCodeNames.put("BAR", "bar");
		featureCodeNames.put("BCH", "beach");
		featureCodeNames.put("BCHS", "beaches");
		featureCodeNames.put("BDLD", "badlands");
		featureCodeNames.put("BLDR", "boulder field");
		featureCodeNames.put("BLHL", "blowhole");
		featureCodeNames.put("BLOW", "blowout");
		featureCodeNames.put("BNCH", "bench");
		featureCodeNames.put("BUTE", "butte");
		featureCodeNames.put("CAPE", "cape");
		featureCodeNames.put("CFT", "cleft");
		featureCodeNames.put("CLDA", "caldera");
		featureCodeNames.put("CLF", "cliff");
		featureCodeNames.put("CNYN", "canyon");
		featureCodeNames.put("CONE", "cone");
		featureCodeNames.put("CRDR", "corridor");
		featureCodeNames.put("CRQ", "cirque");
		featureCodeNames.put("CRQS", "cirques");
		featureCodeNames.put("CRTR", "crater");
		featureCodeNames.put("CUET", "cuesta");
		featureCodeNames.put("DLTA", "delta");
		featureCodeNames.put("DPR", "depression");
		featureCodeNames.put("DSRT", "desert");
		featureCodeNames.put("DUNE", "dune");
		featureCodeNames.put("DVD", "divide");
		featureCodeNames.put("ERG", "sandy desert");
		featureCodeNames.put("FAN", "fan");
		featureCodeNames.put("FORD", "ford");
		featureCodeNames.put("FSR", "fissure");
		featureCodeNames.put("GAP", "gap");
		featureCodeNames.put("GRGE", "gorge");
		featureCodeNames.put("HDLD", "headland");
		featureCodeNames.put("HLL", "hill");
		featureCodeNames.put("HLLS", "hills");
		featureCodeNames.put("HMCK", "hammock");
		featureCodeNames.put("HMDA", "rock desert");
		featureCodeNames.put("INTF", "interfluve");
		featureCodeNames.put("ISL", "island");
		featureCodeNames.put("ISLET", "islet");
		featureCodeNames.put("ISLF", "artificial island");
		featureCodeNames.put("ISLM", "mangrove island");
		featureCodeNames.put("ISLS", "islands");
		featureCodeNames.put("ISLT", "land-tied island");
		featureCodeNames.put("ISLX", "section of island");
		featureCodeNames.put("ISTH", "isthmus");
		featureCodeNames.put("KRST", "karst area");
		featureCodeNames.put("LAVA", "lava area");
		featureCodeNames.put("LEV", "levee");
		featureCodeNames.put("MESA", "mesa");
		featureCodeNames.put("MND", "mound");
		featureCodeNames.put("MRN", "moraine");
		featureCodeNames.put("MT", "mountain");
		featureCodeNames.put("MTS", "mountains");
		featureCodeNames.put("NKM", "meander neck");
		featureCodeNames.put("NTK", "nunatak");
		featureCodeNames.put("NTKS", "nunataks");
		featureCodeNames.put("PAN", "pan");
		featureCodeNames.put("PANS", "pans");
		featureCodeNames.put("PASS", "pass");
		featureCodeNames.put("PEN", "peninsula");
		featureCodeNames.put("PENX", "section of peninsula");
		featureCodeNames.put("PK", "peak");
		featureCodeNames.put("PKS", "peaks");
		featureCodeNames.put("PLAT", "plateau");
		featureCodeNames.put("PLATX", "section of plateau");
		featureCodeNames.put("PLDR", "polder");
		featureCodeNames.put("PLN", "plain");
		featureCodeNames.put("PLNX", "section of plain");
		featureCodeNames.put("PROM", "promontory");
		featureCodeNames.put("PT", "point");
		featureCodeNames.put("PTS", "points");
		featureCodeNames.put("RDGB", "beach ridge");
		featureCodeNames.put("RDGE", "ridge");
		featureCodeNames.put("REG", "stony desert");
		featureCodeNames.put("RK", "rock");
		featureCodeNames.put("RKFL", "rockfall");
		featureCodeNames.put("RKS", "rocks");
		featureCodeNames.put("SAND", "sand area");
		featureCodeNames.put("SBED", "dry stream bed");
		featureCodeNames.put("SCRP", "escarpment");
		featureCodeNames.put("SDL", "saddle");
		featureCodeNames.put("SHOR", "shore");
		featureCodeNames.put("SINK", "sinkhole");
		featureCodeNames.put("SLID", "slide");
		featureCodeNames.put("SLP", "slope");
		featureCodeNames.put("SPIT", "spit");
		featureCodeNames.put("SPUR", "spur");
		featureCodeNames.put("TAL", "talus slope");
		featureCodeNames.put("TRGD", "interdune trough");
		featureCodeNames.put("TRR", "terrace");
		featureCodeNames.put("UPLD", "upland");
		featureCodeNames.put("VAL", "valley");
		featureCodeNames.put("VALG", "hanging valley");
		featureCodeNames.put("VALS", "valleys");
		featureCodeNames.put("VALX", "section of valley");
		featureCodeNames.put("VLC", "volcano");
		featureCodeNames.put("APNU", "apron");
		featureCodeNames.put("ARCU", "arch");
		featureCodeNames.put("ARRU", "arrugado");
		featureCodeNames.put("BDLU", "borderland");
		featureCodeNames.put("BKSU", "banks");
		featureCodeNames.put("BNKU", "bank");
		featureCodeNames.put("BSNU", "basin");
		featureCodeNames.put("CDAU", "cordillera");
		featureCodeNames.put("CNSU", "canyons");
		featureCodeNames.put("CNYU", "canyon");
		featureCodeNames.put("CRSU", "continental rise");
		featureCodeNames.put("DEPU", "deep");
		featureCodeNames.put("EDGU", "shelf edge");
		featureCodeNames.put("ESCU", "escarpment");
		featureCodeNames.put("FANU", "fan");
		featureCodeNames.put("FLTU", "flat");
		featureCodeNames.put("FRZU", "fracture zone");
		featureCodeNames.put("FURU", "furrow");
		featureCodeNames.put("GAPU", "gap");
		featureCodeNames.put("GLYU", "gully");
		featureCodeNames.put("HLLU", "hill");
		featureCodeNames.put("HLSU", "hills");
		featureCodeNames.put("HOLU", "hole");
		featureCodeNames.put("KNLU", "knoll");
		featureCodeNames.put("KNSU", "knolls");
		featureCodeNames.put("LDGU", "ledge");
		featureCodeNames.put("LEVU", "levee");
		featureCodeNames.put("MESU", "mesa");
		featureCodeNames.put("MNDU", "mound");
		featureCodeNames.put("MOTU", "moat");
		featureCodeNames.put("MTU", "mountain");
		featureCodeNames.put("PKSU", "peaks");
		featureCodeNames.put("PKU", "peak");
		featureCodeNames.put("PLNU", "plain");
		featureCodeNames.put("PLTU", "plateau");
		featureCodeNames.put("PNLU", "pinnacle");
		featureCodeNames.put("PRVU", "province");
		featureCodeNames.put("RDGU", "ridge");
		featureCodeNames.put("RDSU", "ridges");
		featureCodeNames.put("RFSU", "reefs");
		featureCodeNames.put("RFU", "reef");
		featureCodeNames.put("RISU", "rise");
		featureCodeNames.put("SCNU", "seachannel");
		featureCodeNames.put("SCSU", "seachannels");
		featureCodeNames.put("SDLU", "saddle");
		featureCodeNames.put("SHFU", "shelf");
		featureCodeNames.put("SHLU", "shoal");
		featureCodeNames.put("SHSU", "shoals");
		featureCodeNames.put("SHVU", "shelf valley");
		featureCodeNames.put("SILU", "sill");
		featureCodeNames.put("SLPU", "slope");
		featureCodeNames.put("SMSU", "seamounts");
		featureCodeNames.put("SMU", "seamount");
		featureCodeNames.put("SPRU", "spur");
		featureCodeNames.put("TERU", "terrace");
		featureCodeNames.put("TMSU", "tablemounts");
		featureCodeNames.put("TMTU", "tablemount");
		featureCodeNames.put("TNGU", "tongue");
		featureCodeNames.put("TRGU", "trough");
		featureCodeNames.put("TRNU", "trench");
		featureCodeNames.put("VALU", "valley");
		featureCodeNames.put("VLSU", "valleys");
		featureCodeNames.put("BUSH", "bush");
		featureCodeNames.put("CULT", "cultivated area");
		featureCodeNames.put("FRST", "forest");
		featureCodeNames.put("FRSTF", "fossilized forest");
		featureCodeNames.put("GRSLD", "grassland");
		featureCodeNames.put("GRVC", "coconut grove");
		featureCodeNames.put("GRVO", "olive grove");
		featureCodeNames.put("GRVP", "palm grove");
		featureCodeNames.put("GRVPN", "pine grove");
		featureCodeNames.put("HTH", "heath");
		featureCodeNames.put("MDW", "meadow");
		featureCodeNames.put("OCH", "orchard");
		featureCodeNames.put("SCRB", "scrubland");
		featureCodeNames.put("TREE", "tree");
		featureCodeNames.put("TUND", "tundra");
		featureCodeNames.put("VIN", "vineyard");
		featureCodeNames.put("VINS", "vineyards");
	}
	
	/**
	 * Returns the 10 results of the search of the given location name on GeoNames.
	 * @param location location to find
	 * @return 10 results from the search on GeoNames
	 */	
	public List<Toponym> search(String location) {
		List<Toponym> toponyms = new ArrayList<Toponym>();
		ToponymSearchCriteria searchCriteria = new ToponymSearchCriteria();
		searchCriteria.setMaxRows(10);
		searchCriteria.setQ(location);
		searchCriteria.setStyle(Style.FULL);
		ToponymSearchResult searchResult = null;
		try {
			searchResult = WebService.search(searchCriteria);
			if(searchResult!=null && !searchResult.getToponyms().isEmpty())
				toponyms = searchResult.getToponyms();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return toponyms;
	}
	
	/**
	 * This method returns the hierarchy for the given location Toponym.
	 * @param location location which the hierarchy is returned for
	 * @return hierarchy for the given location Toponym
	 */
	public List<Toponym> hierarchy(Toponym location) {
		List<Toponym> hierarchy = new ArrayList<Toponym>();
		try {
			hierarchy = WebService.hierarchy(location.getGeoNameId(), "en", Style.SHORT);
		} catch (Exception e) {				
			e.printStackTrace();
		}		
		return hierarchy;
	}
	
	/**
	 * Returns the list of names in the hierarchy for the given location Toponym.
	 * @param location location which the hierarchy is returned for
	 * @return list of names in the hierarchy for the given location Toponym
	 */
	public List<String> hierarchyToString(Toponym location) {
		if(location==null)
			return null;
		List<Toponym> hier = hierarchy(location);
		List<String> strings = new ArrayList<String>();
		for(Toponym t : hier)
			strings.add(t.getName());
		if(strings.isEmpty())
			return null;
		return strings;
	}
	
	/**
	 * Filters the results of a search by selecting only the ones with the name (of an alternateName) exactly equal to the name of the location to find.
	 * @param toponyms list of results to filter
	 * @param name name of the location
	 * @return filtered list
	 */
	public List<Toponym> filterResults(List<Toponym> toponyms, String name) {
		if(toponyms==null || toponyms.isEmpty() || name==null || name.isEmpty())
			return null;
		List<Toponym> filtered = new ArrayList<Toponym>();
		for(Toponym t : toponyms) {
			List<String> alternateNames = null;
			try {
				alternateNames = Arrays.asList(t.getAlternateNames().split(","));
			} catch (InsufficientStyleException e) {
				e.printStackTrace();
			}
			if(t.getName().equalsIgnoreCase(name) || (alternateNames!=null && !alternateNames.isEmpty() && alternateNames.contains(name)))
				filtered.add(t);
		}
		return filtered;
	}
	
	/*public List<Toponym> orderResults(List<Toponym> toponyms, String name) {
		if(toponyms==null || toponyms.isEmpty() || name==null || name.isEmpty())
			return null;
		List<Toponym> orderedList = new ArrayList<Toponym>();
		orderedList.add(toponyms.get(0));
		Iterator<Toponym> ordItr = null;
		int i;
		boolean done = false;
		for(Toponym toponym : toponyms) {
			ordItr = orderedList.iterator();
			i = 0;
			done=false;
			while(ordItr.hasNext() && done==false){
				try {
					if(toponym.getAlternateNames().length()>ordItr.next().getAlternateNames().length()) {
						orderedList.add(i, toponym);
						done=true;
					}
					else
						if(i==orderedList.size())
							orderedList.add(toponym);
				} catch (InsufficientStyleException e) {
					e.printStackTrace();
				}
				i++;					
			}
		}
		return orderedList;
	}*/
	
	/**
	 * Select the best result of a search on GeoNames.<br>
	 * The best result is the first result in a filtered list.
	 * @param toponyms list of results to filter (cadidates for best result)
	 * @param name name of the location
	 * @see #filterResults(List, String)
	 */
	public Toponym getBestResult(List<Toponym> toponyms, String name) {
		if(toponyms==null || toponyms.isEmpty() || name==null || name.isEmpty())
			return null;
		List<Toponym> results = filterResults(toponyms, name);
		if(results!=null && !results.isEmpty())
			return results.get(0);
		return null;
	}
	
	/**
	 * Converts a Toponym (GeoNames Class) to a GeoEntity (NLP-Geo Class).
	 * @param t toponym to convert
	 * @return the corresponding GeoEntity
	 */
	public GeoEntity toGeoEntity(Toponym t) {
		if(t==null)
			return null;
		String geoType = featureCodeNames.get(t.getFeatureCode());
		List<Toponym> hierarchy = hierarchy(t);
		Toponym temp = null;
		if(hierarchy.size()>1)
			temp = hierarchy.get(hierarchy.size()-2);
		else
			temp = hierarchy.get(hierarchy.size()-1);
		String isLocatedIn = temp.getName()+"("+featureCodeNames.get(temp.getFeatureCode())+")";
		return new GeoEntity(t.getName(), geoType, Integer.toString(t.getGeoNameId()), isLocatedIn, Double.valueOf(t.getLatitude()), Double.valueOf(t.getLongitude()));
	}
}
